<!DOCTYPE html>
<html>
<head>
    

    

    



    <meta charset="utf-8">
    
    
    
    
    <title>详细分析Redis的持久化操作 | 博客主页 | 世界是个球，前方总有路！</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    
    <meta name="theme-color" content="#3F51B5">
    
    
    <meta name="keywords" content="Redis">
    <meta name="description" content="一、前言&amp;emsp;&amp;emsp;由于疫情的原因，学校还没有开学，这也就让我有了很多的时间。趁着时间比较多，我终于可以开始学习那些之前一直想学的技术了。最近这几天开始学习Redis，买了本《Redis实战》，看到了第四章，前三章都是讲一些Redis的基本使用以及命令，第四章才开始涉及到原理相关的内容。《Redis实战》的第四章涉及到了Redis的持久化、主从复制以及事务等内容，我个人认为这些应该属于">
<meta property="og:type" content="article">
<meta property="og:title" content="详细分析Redis的持久化操作">
<meta property="og:url" content="http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/index.html">
<meta property="og:site_name" content="博客主页">
<meta property="og:description" content="一、前言&amp;emsp;&amp;emsp;由于疫情的原因，学校还没有开学，这也就让我有了很多的时间。趁着时间比较多，我终于可以开始学习那些之前一直想学的技术了。最近这几天开始学习Redis，买了本《Redis实战》，看到了第四章，前三章都是讲一些Redis的基本使用以及命令，第四章才开始涉及到原理相关的内容。《Redis实战》的第四章涉及到了Redis的持久化、主从复制以及事务等内容，我个人认为这些应该属于">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2020-04-25T14:01:29.000Z">
<meta property="article:modified_time" content="2020-04-25T17:08:11.270Z">
<meta property="article:author" content="特务依昂">
<meta property="article:tag" content="Redis">
<meta name="twitter:card" content="summary">
    
        <link rel="alternate" type="application/atom+xml" title="博客主页" href="/blog/atom.xml">
    
    <link rel="shortcut icon" href="/blog/img/title.png">
    <link rel="stylesheet" href="//unpkg.com/hexo-theme-material-indigo@latest/css/style.css">
    <script>window.lazyScripts=[]</script>

    <!-- custom head -->
    

<meta name="generator" content="Hexo 4.2.0"></head>

<body>
    <div id="loading" class="active"></div>

    <aside id="menu" class="hide" >
  <div class="inner flex-row-vertical">
    <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menu-off">
        <i class="icon icon-lg icon-close"></i>
    </a>
    <div class="brand-wrap" style="background-image:url(/blog/img/brand.jpg)">
      <div class="brand">
        <a href="/blog/" class="avatar waves-effect waves-circle waves-light">
          <img src="/blog/img/avatar.jpg">
        </a>
        <hgroup class="introduce">
          <h5 class="nickname">特务依昂</h5>
          <a href="mailto:1131564805@qq.com" title="1131564805@qq.com" class="mail">1131564805@qq.com</a>
        </hgroup>
      </div>
    </div>
    <div class="scroll-wrap flex-col">
      <ul class="nav">
        
            <li class="waves-block waves-effect">
              <a href="/blog/"  >
                <i class="icon icon-lg icon-home"></i>
                主页
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/archives"  >
                <i class="icon icon-lg icon-archives"></i>
                博客
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/tags"  >
                <i class="icon icon-lg icon-tags"></i>
                标签
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/blog/categories"  >
                <i class="icon icon-lg icon-th-list"></i>
                分类
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://github.com/tewuyiang" target="_blank" >
                <i class="icon icon-lg icon-github"></i>
                Github
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://weibo.com/u/5516635708/" target="_blank" >
                <i class="icon icon-lg icon-weibo"></i>
                Weibo
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://www.cnblogs.com/tuyang1129/" target="_blank" >
                <i class="icon icon-lg icon-link"></i>
                博客园
              </a>
            </li>
        
      </ul>
    </div>
  </div>
</aside>

    <main id="main">
        <header class="top-header" id="header">
    <div class="flex-row">
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light on" id="menu-toggle">
          <i class="icon icon-lg icon-navicon"></i>
        </a>
        <div class="flex-col header-title ellipsis">详细分析Redis的持久化操作</div>
        
        <div class="search-wrap" id="search-wrap">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="back">
                <i class="icon icon-lg icon-chevron-left"></i>
            </a>
            <input type="text" id="key" class="search-input" autocomplete="off" placeholder="输入感兴趣的关键字">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="search">
                <i class="icon icon-lg icon-search"></i>
            </a>
        </div>
        
        
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menuShare">
            <i class="icon icon-lg icon-share-alt"></i>
        </a>
        
    </div>
</header>
<header class="content-header post-header">

    <div class="container fade-scale">
        <h1 class="title">详细分析Redis的持久化操作</h1>
        <h5 class="subtitle">
            
                <time datetime="2020-04-25T14:01:29.000Z" itemprop="datePublished" class="page-time">
  2020-04-25
</time>


	<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/blog/categories/Redis/">Redis</a></li></ul>

            
        </h5>
    </div>

    


</header>


<div class="container body-wrap">
    
    <aside class="post-widget">
        <nav class="post-toc-wrap post-toc-shrink" id="post-toc">
            <h4>TOC</h4>
            <ol class="post-toc"><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#一、前言"><span class="post-toc-number">1.</span> <span class="post-toc-text">一、前言</span></a></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#二、正文"><span class="post-toc-number">2.</span> <span class="post-toc-text">二、正文</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-1-为什么需要持久化"><span class="post-toc-number">2.1.</span> <span class="post-toc-text">2.1 为什么需要持久化</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-2-Redis的持久化方式"><span class="post-toc-number">2.2.</span> <span class="post-toc-text">2.2 Redis的持久化方式</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-3-快照持久化（RDB）"><span class="post-toc-number">2.3.</span> <span class="post-toc-text">2.3 快照持久化（RDB）</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-4-执行快照持久化的方式"><span class="post-toc-number">2.4.</span> <span class="post-toc-text">2.4 执行快照持久化的方式</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-5-快照持久化的优缺点"><span class="post-toc-number">2.5.</span> <span class="post-toc-text">2.5 快照持久化的优缺点</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-6-AOF持久化"><span class="post-toc-number">2.6.</span> <span class="post-toc-text">2.6 AOF持久化</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-7-AOF的重写机制"><span class="post-toc-number">2.7.</span> <span class="post-toc-text">2.7 AOF的重写机制</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-8-AOF的错误处理"><span class="post-toc-number">2.8.</span> <span class="post-toc-text">2.8 AOF的错误处理</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-9-AOF的优缺点"><span class="post-toc-number">2.9.</span> <span class="post-toc-text">2.9 AOF的优缺点</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-10-选择快照还是AOF？"><span class="post-toc-number">2.10.</span> <span class="post-toc-text">2.10 选择快照还是AOF？</span></a></li></ol></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#三、总结"><span class="post-toc-number">3.</span> <span class="post-toc-text">三、总结</span></a></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#四、参考"><span class="post-toc-number">4.</span> <span class="post-toc-text">四、参考</span></a></li></ol>
        </nav>
    </aside>


<article id="post-详细分析Redis的持久化操作"
  class="post-article article-type-post fade" itemprop="blogPost">

    <div class="post-card">
        <h1 class="post-card-title">详细分析Redis的持久化操作</h1>
        <div class="post-meta">
            <time class="post-time" title="2020-04-25 22:01:29" datetime="2020-04-25T14:01:29.000Z"  itemprop="datePublished">2020-04-25</time>

            
	<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/blog/categories/Redis/">Redis</a></li></ul>



            
<span id="busuanzi_container_page_pv" title="文章总阅读量" style='display:none'>
    <i class="icon icon-eye icon-pr"></i><span id="busuanzi_value_page_pv"></span>
</span>


        </div>
        <div class="post-content" id="post-content" itemprop="postContent">
            <h1 id="一、前言"><a href="#一、前言" class="headerlink" title="一、前言"></a>一、前言</h1><p>&emsp;&emsp;由于疫情的原因，学校还没有开学，这也就让我有了很多的时间。趁着时间比较多，我终于可以开始学习那些之前一直想学的技术了。最近这几天开始学习<code>Redis</code>，买了本<code>《Redis实战》</code>，看到了第四章，前三章都是讲一些<code>Redis</code>的基本使用以及命令，第四章才开始涉及到原理相关的内容。<code>《Redis实战》</code>的第四章涉及到了<code>Redis</code>的持久化、主从复制以及事务等内容，我个人认为这些应该属于<code>Redis</code>中比较重要的部分，也是面试的常考内容。这篇博客就来记录一下<code>Redis</code>的持久化机制。</p>
<br>

<h1 id="二、正文"><a href="#二、正文" class="headerlink" title="二、正文"></a>二、正文</h1><h2 id="2-1-为什么需要持久化"><a href="#2-1-为什么需要持久化" class="headerlink" title="2.1 为什么需要持久化"></a>2.1 为什么需要持久化</h2><p>&emsp;&emsp;学习过<code>Redis</code>的应该都知道，<code>Redis</code>与<code>MySQL</code>等关系型数据库不同，它的数据不是存储在硬盘中，而是存放在内存，所以<code>Redis</code>的速度非常快。而这也就会造成一个问题：<strong>电脑如果宕机，或者由于某些原因需要重启，此时内存中的数据就会丢失</strong>。<code>Redis</code>既然把数据存放在内存，自然也就无法避免这个问题。所以，为了在电脑重启后，能够恢复原来的数据，<code>Redis</code>就需要提供持久化的机制，将<code>Redis</code>数据库存储在内存中的数据，在磁盘中进行备份，也就是持久化。而当<code>Redis</code>重启后，去磁盘中将持久化的数据重新读取到内存，便能避免数据的丢失。</p>
<br>

<h2 id="2-2-Redis的持久化方式"><a href="#2-2-Redis的持久化方式" class="headerlink" title="2.2 Redis的持久化方式"></a>2.2 Redis的持久化方式</h2><p>&emsp;&emsp;<code>Redis</code>提供了两种持久化的方式，分别是：</p>
<ul>
<li>快照持久化；</li>
<li>AOF持久化；</li>
</ul>
<p>&emsp;&emsp;下面我就来详细地介绍这两种持久化的方式。</p>
<br>

<h2 id="2-3-快照持久化（RDB）"><a href="#2-3-快照持久化（RDB）" class="headerlink" title="2.3 快照持久化（RDB）"></a>2.3 快照持久化（RDB）</h2><p>&emsp;&emsp;快照持久化也就做<code>RDB</code>持久化。快照持久化的实现方式简单来说就是：<strong>Redis将当前内存中存储的数据写入到一个文件中，将这个文件作为Redis当前的一个快照，保存在磁盘中。当Redis重启时，将这个快照文件中存储的内容加载进内存，即可恢复Redis之前的状态</strong>。默认情况下，<code>Redis</code>将快照保存在一个叫做<code>dump.rdb</code>的文件中，我们也可以在配置文件中，通过<code>dbfilename</code>选项来设置快照文件的名称；默认情况下快照文件就保存在<code>Redis</code>的安装目录下，我们可以在配置文件中，通过<code>dir</code>选项来配置快照文件的存储路径（其实也是AOF的路径）。</p>
<br>

<h2 id="2-4-执行快照持久化的方式"><a href="#2-4-执行快照持久化的方式" class="headerlink" title="2.4 执行快照持久化的方式"></a>2.4 执行快照持久化的方式</h2><p>&emsp;&emsp;执行快照持久化有两种方式：</p>
<p>&emsp;<strong>2.4.1 使用配置文件</strong></p>
<p>&emsp;&emsp;第一种方式就是在<code>Redis</code>的配置文件中（<code>windows</code>下这个文件叫<code>redis.windows-service.conf</code>）加上<code>save</code>配置项，比如像下面这样：</p>
<blockquote>
<p><strong>save 60 100</strong>：在配置文件中加上这一条的意思是，Redis会每60秒检查一次，若在这60秒中，Redis数据库执行了100次以上的写操作，那Redis就会生成一个快照文件，替换原来的快照文件；若不满足这个条件，则不生成快照，继续等待60秒；</p>
</blockquote>
<p>&emsp;&emsp;我们可以根据自己的需求，调整每次等待的时间，以及对写操作次数的要求。而且，我们可以在配置文件中，添加多个<code>save</code>选项，比如一个<code>save 60 100</code>，一个<code>save 5 10</code>，则<code>Redis</code>每<code>5</code>秒以及每<code>100</code>秒都会判断一次。需要注意的是，我们不应该让生成快照太过频繁，因为这是一个比较消耗资源的工作，会降低<code>Redis</code>的响应速度。</p>
<br>

<p>&emsp;<strong>2.4.2 使用指令</strong></p>
<p>&emsp;&emsp;执行快照持久化的第二个方法就是使用<code>Redis</code>指令，<code>Redis</code>提供了两个指令来请求服务器进行快照持久化，这两个指令分别是<strong>SAVE</strong>和<strong>BGSAVE</strong>。</p>
<p>&emsp;<strong>（a）BGSAVE指令</strong></p>
<p>&emsp;&emsp;<code>BGSAVE</code>的执行流程如下：</p>
<ol>
<li><code>Redis</code>调用系统的<code>fork()</code>，创建出一个子进程；</li>
<li>子进程将当前<code>Redis</code>中的数据，写入到一个临时文件中；同时父进程不受影响，继续执行客户端的请求；</li>
<li>子进程将所有的数据写入到了临时文件后，于是使用这个文件替换原来的快照文件（默认是<code>dump.rdb</code>）；</li>
</ol>
<p>&emsp;&emsp;值得一提的是，通过配置文件执行快照持久化的方式，实际上就是<code>Redis</code>在判断满足条件时，调用<code>BGSAVE</code>指令来实现的。</p>
<p>&emsp;<strong>（b）SAVE指令</strong></p>
<p>&emsp;&emsp;<code>SAVE</code>指令生成快照的方式与<code>BGSAVE</code>不同，<code>Redis</code>执行<code>SAVE</code>指令时，不会创建一个子进程，异步的生成快照文件，而是直接使用<code>Redis</code>当前进程。执行<code>SAVE</code>指令在创建快照的过程中，<code>Redis</code>服务器会阻塞所有的<code>Redis</code>客户端，直到快照生成完毕，并更新到磁盘之后，才会继续执行客户端发来的增删改查的指令。</p>
<p>&emsp;&emsp;当然，这个指令一般很少使用，因为会阻塞客户端，造成停顿。但是实际上，这个指令的执行效率一般比<code>BGSAVE</code>更高，因为不需要创建子进程，而且在这个过程中，其他操作被阻塞，<code>Redis</code>服务器一心一意地生成快照。在<code>《Redis实战》</code>中，作者提到了使用<code>SAVE</code>指令的一个案例：</p>
<blockquote>
<p> &emsp;&emsp;当前服务器的Redis数据库中保存了大量数据，使用BGSAVE指令生成快照会非常的耗时 ，而且由于所剩内存不多，甚至无法创建子进程，于是作者编写了一个shell脚本，这个脚本的内容就是让服务器每天凌晨3点，执行SAVE命令，生成快照，这样就不需要创建子进程，而且由于是凌晨三点，用户较少，SAVE的阻塞机制也不会有太大的影响。</p>
</blockquote>
<br>

<h2 id="2-5-快照持久化的优缺点"><a href="#2-5-快照持久化的优缺点" class="headerlink" title="2.5 快照持久化的优缺点"></a>2.5 快照持久化的优缺点</h2><p><strong>（1）优点：</strong></p>
<ol>
<li><p>快照的<code>rdb</code>文件是一个经过压缩的紧凑文件，它保存了<code>Redis</code>在某个时间点上的数据集，这个文件非常适合用来备份。我们可以存储<code>Redis</code>服务器在不同时间点上的<code>rbd</code>文件，比如说一小时存储一次，一个月存储一次，这样就可以在遇到问题或有特殊需求时，将<code>Redis</code>恢复到某一个时间点；</p>
</li>
<li><p>RDB非常适用于灾难恢复（disaster recovery）：它只有一个文件，并且内容都非常紧凑，可以（在加密后）将它传送到别的服务器上；</p>
</li>
<li><p>RDB 可以最大化 Redis 的性能：父进程在保存 <code>RDB</code> 文件时唯一要做的就是 <code>fork</code> 出一个子进程，然后这个子进程就会处理接下来的所有保存工作，父进程无须执行任何磁盘<code>I/O</code>操作，所以不会影响父进程处理客户端的请求；</p>
</li>
<li><p><code>RDB</code> 在恢复大数据集时的速度比<code>AOF</code> 的恢复速度要快。</p>
</li>
</ol>
<p><strong>（2）缺点</strong>：</p>
<ol>
<li>当我们的服务器发生异常，导致停机时，那我们将会丢失最后一次创建快照后，所作的所有写操作，因为这些操作发生在内存中，还没来得及同步到磁盘。比如我们在配置文件中配置每<code>5</code>分钟生成一次快照，那当系统发生故障导致宕机时，我们将会丢失好几分钟内的操作；</li>
<li>每次执行<code>BGSAVE</code>创建快照，都需要先创建出一个子进程，再由子进程执行后续操作，当内存中数据较大时，创建一个子进程将会非常耗时，造成服务器等待数毫秒，甚至达到一秒，影响用户体验。而且从这一点也可以说明，我们不能通过提高生成快照的频率，来解决第一个缺点；</li>
</ol>
<br>

<h2 id="2-6-AOF持久化"><a href="#2-6-AOF持久化" class="headerlink" title="2.6 AOF持久化"></a>2.6 AOF持久化</h2><p>&emsp;&emsp;<code>AOF</code>全称为只追加文件（append-only file），它的实现方式简单来说就是：<strong>AOF持久化机制，会将Redis执行的所有写指令，追加到到AOF的末尾，当服务器发生宕机，或者由于某些原因需要重启时，在重启后，读取AOF文件，重新执行其中记录的写操作，以此达到恢复数据的目的。</strong></p>
<p>&emsp;&emsp;<code>AOF</code>持久化机制默认是关闭的，我们可以在配置文件中，配置<strong>appendonly yes</strong>来开启。同时我们也可以通过配置<strong>appendfsync</strong>，控制写操作追加到<code>AOF</code>中的频率，它有如下三种选项：</p>
<ul>
<li><strong>always</strong>：<code>Redis</code>每次执行写指令，都会立即将这个写指令同步到<code>AOF</code>中；使用这个选项时，<code>Redis</code>发生异常，则最多只会丢失一次写操作（也就是在同步的过程中宕机，没同步完成），但是这也会导致<code>Redis</code>的响应速度变慢，因为此选项会造成频繁的<code>IO</code>操作；</li>
<li><strong>everysec（默认）</strong>：每秒同步一次，使用此选项，速度足够快，而且发生宕机时也只会丢失<code>1s</code>内的写操作；</li>
<li><strong>no</strong>：让操作系统来决定什么时候进行同步，这个选项速度更快，但是不安全，宕机时丢失数据的多少是不确定的；</li>
</ul>
<p>&emsp;&emsp;推荐（也是默认），使用第二个选项<code>everysec</code>，每秒进行一次同步，因为这个选项兼顾了速度与安全性，而第一个选项太慢，第三个选项无法保证安全性。</p>
<br>

<h2 id="2-7-AOF的重写机制"><a href="#2-7-AOF的重写机制" class="headerlink" title="2.7 AOF的重写机制"></a>2.7 AOF的重写机制</h2><p>&emsp;&emsp;<code>AOF</code>持久化的执行机制就是，不断地将写指令追加到<code>AOF</code>的末尾，这样就会导致<code>AOF</code>越来越大。为了解决<code>AOF</code>越来越大的问题，<code>Redis</code>实现了一种优化机制——<strong>AOF重写</strong>。当<code>Redis</code>检查到<code>AOF</code>已经很大时，就会触发重写机制，优化其中的内容，将它优化为能够得到相同结果的最小的指令集合。</p>
<p>&emsp;&emsp;比如说，我们在<code>Redis</code>中使用<code>SET</code>指令创建了一个<code>String</code>类型的数据，最后使用<code>DEL</code>指令将它删除了。如果开启了<code>AOF</code>持久化，那么则<code>AOF</code>中，将会记录这条<code>SET</code>和<code>DEL</code>指令。但是，在执行重写的过程中，这个String最后被删除了，那么<code>Redis</code>就不会将这两条指令加入新的<code>AOF</code>中，因为已经被删除的数据，不需要恢复。再比如说，我们使用<code>Redis</code>维护了一个计数器<code>cnt</code>，我们使用了<code>100</code>次<code>INCR</code>指令，让<code>cnt</code>自增到了<code>100</code>，而<code>Redis</code>重写<code>AOF</code>时，可以将这<code>100</code>条<code>incr</code>修改为一条<code>SET</code>指令，直接将<code>cnt</code>设置为<code>100</code>，而不是保留<code>100</code>条<code>INCR</code>。</p>
<p>&emsp;&emsp;经过了重写后，<code>AOF</code>的大小将会大大减小，而且也去除了不必要的操作，优化了恢复数据的指令集。而<code>AOF</code>重写的过程与生成一个快照文件类似，如下：</p>
<ol>
<li><code>Redis</code>执行<code>fock()</code>，创建一个子进程用来执行后续操作，而父进程继续处理发送到<code>Redis</code>的执行请求；</li>
<li>子进程重写旧<code>AOF</code>文件，将重写后的内容写入到一个临时文件；</li>
<li>如果这个过程中，有新的写指令到达，那么<code>Redis</code>会将这些写指令依旧追加到旧的<code>AOF</code>中，同时也会将这些指令加入到内存的一个缓冲区中。这样做的目的是，如果服务器发生异常，<code>AOF</code>重写失败，这些指令依然能够保存在旧<code>AOF</code>，不会丢失；</li>
<li>当子进程完成重写工作时，它给父进程发送一个信号，父进程在接收到信号之后，将内存缓存中的所有写指令追加到新 <code>AOF</code> 文件的末尾；</li>
<li>使用新<code>AOF</code>替换旧的<code>AOF</code>，这之后执行的所有写指令都将追加到新的<code>AOF</code>中；</li>
</ol>
<br>

<h2 id="2-8-AOF的错误处理"><a href="#2-8-AOF的错误处理" class="headerlink" title="2.8 AOF的错误处理"></a>2.8 AOF的错误处理</h2><p>&emsp;&emsp;<code>AOF</code>文件是有可能发生错误的，比如上面提过，如果当前<code>Redis</code>正在向<code>AOF</code>中追加一个写指令，但是此时服务器宕机，那么这个存入<code>AOF</code>中的这个写指令就是不完整的，也就是<code>AOF</code>出现了错误。如果停机造成了 <code>AOF</code> 文件出错（corrupt）， 那么 <code>Redis</code> 在重启时会拒绝载入这个 <code>AOF</code> 文件， 从而确保数据的一致性不会被破坏。</p>
<p>&emsp;&emsp;那么，当<code>AOF</code>发生了错误，应该如何处理呢？我们可以使用如下命令：</p>
<blockquote>
<p><strong>redis-check-aof –fix</strong>：redis-check-aof用来检测AOF是否存在错误，如果指定了–fix参数，那么Redis在检测到AOF的错误后，会对AOF进行修复。</p>
</blockquote>
<p>&emsp;&emsp;<code>redis-check-aof</code>修复<code>AOF</code>的方式非常简单：<strong>扫描AOF文件，寻找其中不正确或不完整的指令，当发现第一个出错的指令后，就将这个指令以及这之后的所有指令删除</strong>。为什么需要删除出错指令之后的所有指令呢？因为当一条指令出错，很有可能影响到后续的操作，导致后续操作的都是脏数据，而<code>Redis</code>无法检测哪些指令是受到影响的，所以为了保险起见，就将后续指令全部删除。不过不用担心，因为在大多数情况下，出错的都是<code>AOF</code>最末尾的指令。</p>
<br>

<h2 id="2-9-AOF的优缺点"><a href="#2-9-AOF的优缺点" class="headerlink" title="2.9 AOF的优缺点"></a>2.9 AOF的优缺点</h2><p><strong>（1）优点：</strong></p>
<ol>
<li>使用 <code>AOF</code> 持久化会让 <code>Redis</code> 变得非常耐久，意思就是说，当发生异常导致需要重启服务器时，只会丢失很少的一部分数据，因为<code>AOF</code>持久化默认<code>1s</code>同步一次，也就是说，<code>Redis</code>最多只会丢失<code>1s</code>中所做的修改；</li>
<li><code>Redis</code>可以在 <code>AOF</code> 文件体积变得过大时，自动地在后台对 <code>AOF</code> 进行重写： 重写后的新 <code>AOF</code> 文件包含了恢复当前数据集所需的最小命令集合。 </li>
<li><code>AOF</code> 文件有序地保存了对数据库执行的所有写入操作， 这些写入操作以 <code>Redis</code> 协议的格式保存， 因此 <code>AOF</code> 文件的内容非常容易被人读懂， 对文件进行分析（<code>parse</code>）也很轻松。</li>
<li><code>AOF</code> 文件是一个只进行追加操作的日志文件（<code>append only log</code>）， 因此对 <code>AOF</code> 文件的写入不需要进行 <code>seek</code> ， 即使日志因为某些原因而包含了未写入完整的命令（比如写入时磁盘已满，写入中途停机，等等）， <code>redis-check-aof</code> 工具也可以轻易地修复这种问题。</li>
</ol>
<p><strong>（2）缺点：</strong></p>
<ol>
<li>对于相同的数据集来说，<code>AOF</code> 文件的体积通常要大于快照<code>RDB</code>文件的体积大，因为<code>RDB</code>只存储数据，而<code>AOF</code>中的写指令，既包含指令，也包含数据；</li>
<li>如果<code>AOF</code>体积太大，那么恢复数据将要花费较长的时间，因为需要重做指令；</li>
</ol>
<br>

<h2 id="2-10-选择快照还是AOF？"><a href="#2-10-选择快照还是AOF？" class="headerlink" title="2.10 选择快照还是AOF？"></a>2.10 选择快照还是AOF？</h2><p>&emsp;&emsp;说到这里，可能就有人要问了，在实际生产中，我们应该使用快照持久化还是<code>AOF</code>持久化呢？</p>
<p>1、如果希望自己的数据库有很高的安全性，则应该两者同时使用，<code>AOF</code>用作精确记录，而快照用作数据备份，前面也说过，快照非常适合用来做数据备份，因为它只存储数据库中的数据，并且经过了压缩，而且它恢复<code>Redis</code>数据的速度一般要快于<code>AOF</code>；</p>
<p>2、如果可以容忍一段时间内的数据丢失，则可以考虑只使用快照持久化，减小服务器的开销；</p>
<p>&emsp;&emsp;值得一提的是，如果我们同时开启了快照持久化和<code>AOF</code>持久化，<code>Redis</code>在重启后，会优先选择<code>AOF</code>来恢复数据，因为一般情况下，<code>AOF</code>能够更加完整地恢复数据。</p>
<br>

<h1 id="三、总结"><a href="#三、总结" class="headerlink" title="三、总结"></a>三、总结</h1><p>&emsp;&emsp;快照持久化和<code>AOF</code>持久化各有优劣，在实际生产环境中，我们一般是两者配合使用，快照持久化消耗较低，而且适合用于备份，但是会丢失一段时间的数据；<code>AOF</code>持久化更加地耐久，可靠性更高，但是开销可能相对较高。以上就对<code>Redis</code>的持久化机制做了一个比较详细的介绍，相信看完只后，对<code>Redis</code>会有一个更加深入的理解。</p>
<br>

<h1 id="四、参考"><a href="#四、参考" class="headerlink" title="四、参考"></a>四、参考</h1><ul>
<li>《Redis实战》</li>
<li><a href="http://doc.redisfans.com/topic/persistence.html" target="_blank" rel="noopener">Redis官方文档——持久化</a></li>
</ul>

        </div>

        <blockquote class="post-copyright">
    
    <div class="content">
        
<span class="post-time">
    最后更新时间：<time datetime="2020-04-25T17:08:11.270Z" itemprop="dateUpdated">2020-04-26 01:08:11</time>
</span><br>


        
        世界是个球，前方总有路！
        
    </div>
    
    <footer>
        <a href="http://tewuyiang.gitee.io/blog">
            <img src="/blog/img/avatar.jpg" alt="特务依昂">
            特务依昂
        </a>
    </footer>
</blockquote>

        


        <div class="post-footer">
            
	<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/blog/tags/Redis/" rel="tag">Redis</a></li></ul>


            
<div class="page-share-wrap">
    

<div class="page-share" id="pageShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/&title=《详细分析Redis的持久化操作》 — 博客主页&pic=http://tewuyiang.gitee.io/blog/img/avatar.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/&title=《详细分析Redis的持久化操作》 — 博客主页&source=一个未来程序员的博客~~~" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《详细分析Redis的持久化操作》 — 博客主页&url=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/&via=http://tewuyiang.gitee.io/blog" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>



    <a href="javascript:;" id="shareFab" class="page-share-fab waves-effect waves-circle">
        <i class="icon icon-share-alt icon-lg"></i>
    </a>
</div>



        </div>
    </div>

    
<nav class="post-nav flex-row flex-justify-between">
  
    <div class="waves-block waves-effect prev">
      <a href="/blog/%E6%B7%B1%E5%85%A5%E5%88%86%E6%9E%90Redis%E7%9A%84%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6/" id="post-prev" class="post-nav-link">
        <div class="tips"><i class="icon icon-angle-left icon-lg icon-pr"></i> Prev</div>
        <h4 class="title">深入分析Redis的主从复制</h4>
      </a>
    </div>
  

  
    <div class="waves-block waves-effect next">
      <a href="/blog/%E6%98%A5%E6%8B%9B%E9%9D%A2%E7%BB%8F%E2%80%94%E2%80%94%E7%BD%91%E6%98%93%E4%BA%92%E5%A8%B1%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%BC%80%E5%8F%91%E4%B8%80%E9%9D%A2/" id="post-next" class="post-nav-link">
        <div class="tips">Next <i class="icon icon-angle-right icon-lg icon-pl"></i></div>
        <h4 class="title">春招面经——网易互娱服务端开发一面</h4>
      </a>
    </div>
  
</nav>



    




















</article>



</div>

        <footer class="footer">
    <div class="top">
        
<p>
    <span id="busuanzi_container_site_uv" style='display:none'>
        站点总访客数：<span id="busuanzi_value_site_uv"></span>
    </span>
    <span id="busuanzi_container_site_pv" style='display:none'>
        站点总访问量：<span id="busuanzi_value_site_pv"></span>
    </span>
</p>


        <p>
            
                <span><a href="/blog/atom.xml" target="_blank" class="rss" title="rss"><i class="icon icon-lg icon-rss"></i></a></span>
            
            <span>博客内容遵循 <a rel="license noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank">知识共享 署名 - 非商业性 - 相同方式共享 4.0 国际协议</a></span>
        </p>
    </div>
    <div class="bottom">
        <p><span>特务依昂 &copy; 2015 - 2020</span>
            <span>
                
                Power by <a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://github.com/yscoder/hexo-theme-indigo" target="_blank">indigo</a>
            </span>
        </p>
    </div>
</footer>

    </main>
    <div class="mask" id="mask"></div>
<a href="javascript:;" id="gotop" class="waves-effect waves-circle waves-light"><span class="icon icon-lg icon-chevron-up"></span></a>



<div class="global-share" id="globalShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/&title=《详细分析Redis的持久化操作》 — 博客主页&pic=http://tewuyiang.gitee.io/blog/img/avatar.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/&title=《详细分析Redis的持久化操作》 — 博客主页&source=一个未来程序员的博客~~~" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《详细分析Redis的持久化操作》 — 博客主页&url=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/&via=http://tewuyiang.gitee.io/blog" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://tewuyiang.gitee.io/blog/%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%93%8D%E4%BD%9C/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>


<div class="page-modal wx-share" id="wxShare">
    <a class="close" href="javascript:;"><i class="icon icon-close"></i></a>
    <p>扫一扫，分享到微信</p>
    <img src="" alt="微信分享二维码">
</div>




    <script src="//cdn.bootcss.com/node-waves/0.7.4/waves.min.js"></script>
<script>
var BLOG = { ROOT: '/blog/', SHARE: true, REWARD: false };


</script>

<script src="//unpkg.com/hexo-theme-material-indigo@latest/js/main.min.js"></script>


<div class="search-panel" id="search-panel">
    <ul class="search-result" id="search-result"></ul>
</div>
<template id="search-tpl">
<li class="item">
    <a href="{path}" class="waves-block waves-effect">
        <div class="title ellipsis" title="{title}">{title}</div>
        <div class="flex-row flex-middle">
            <div class="tags ellipsis">
                {tags}
            </div>
            <time class="flex-col time">{date}</time>
        </div>
    </a>
</li>
</template>

<script src="//unpkg.com/hexo-theme-material-indigo@latest/js/search.min.js" async></script>






<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>



<script>
(function() {
    var OriginTitile = document.title, titleTime;
    document.addEventListener('visibilitychange', function() {
        if (document.hidden) {
            document.title = '人呢，怎么不见了！';
            clearTimeout(titleTime);
        } else {
            document.title = '(つェ⊂)咦!欢迎回来!';
            titleTime = setTimeout(function() {
                document.title = OriginTitile;
            },2000);
        }
    });
})();
</script>



</body>
</html>
